/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */

package com.ecarx.systemui.plugin.ui.adapter;

import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.ecarx.module_bluetooth.BTConstants;
import com.ecarx.module_bluetooth.aosp.CachedBluetoothDevice;
import com.ecarx.module_bluetooth.enums.BtProfileEnums;
import com.ecarx.module_bluetooth.enums.ConnectProfileOptionEnum;
import com.ecarx.systemui.plugin.R;
import com.ecarx.systemui.plugin.controller.BluetoothController;
import com.ecarx.systemui.plugin.ui.adapter.entity.ItemBluetooth;
import com.ecarx.systemui.plugin.ui.adapter.entity.ItemTextLabelBluetooth;
import com.ecarx.systemui.plugin.utils.LogUtils;
import com.ecarx.util.Logcat;

import java.util.List;

public class BtDevicesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final String TAG = "BtDevicesAdapter";
    public static final int BLUETOOTH_CONNECTED_VIEW_TYPE = R.layout.item_bluetooth_connected;
    public static final int SCAN_BLUETOOTH_VIEW_TYPE = R.layout.item_scan_bluetooth;
    public static final int TEXT_LABEL_BLUETOOTH_VIEW_TYPE = R.layout.item_bluetooth_text_label;

    private final List<ItemBluetooth> mDatas;
    private TextLabelViewHolder.ScanStateListener mScanStateListener;

    public BtDevicesAdapter(List<ItemBluetooth> datas) {
        this.mDatas = datas;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(viewType, parent, false);
        if (BLUETOOTH_CONNECTED_VIEW_TYPE == viewType) {
            return new ConnectedBluetoothViewHolder(this, view);
        } else if (SCAN_BLUETOOTH_VIEW_TYPE == viewType) {
            return new ScanBluetoothViewHolder(this, view);
        } else {
            return new TextLabelViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof ConnectedBluetoothViewHolder) {
            ConnectedBluetoothViewHolder connectedHolder = (ConnectedBluetoothViewHolder) holder;
            connectedHolder.updateDeviceStatus(holder.itemView.getContext());
        } else if (holder instanceof ScanBluetoothViewHolder) {
            ScanBluetoothViewHolder scanBluetoothViewHolder = (ScanBluetoothViewHolder) holder;
            CachedBluetoothDevice device = mDatas.get(holder.getAdapterPosition()).getData();
            if (device != null) {
                scanBluetoothViewHolder.setName(device.getNameOrAddress());
            }
        } else if (holder instanceof TextLabelViewHolder) {
            TextLabelViewHolder textLabelViewHolder = (TextLabelViewHolder) holder;
            if(mDatas.get(position) instanceof ItemTextLabelBluetooth){
                if(((ItemTextLabelBluetooth)mDatas.get(position)).isMy()){
                    textLabelViewHolder.tvTitle.setText(R.string.bt_my_device);
                } else {
                    textLabelViewHolder.tvTitle.setText(R.string.bt_other_device);
                    mScanStateListener = new TextLabelViewHolder.ScanStateListener() {
                        @Override
                        public void onScanStateChanged(boolean start) {
                            textLabelViewHolder.showLoading(start);
                        }
                    };
                }
            }

        }
    }

    @Override
    public int getItemViewType(int position) {
        return mDatas.get(position).getViewType();
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    public void onScanStateChanged(boolean start) {
        LogUtils.d(TAG, "onScanStateChanged() called with: start = [" + start + "]");
        if (mScanStateListener != null) {
            mScanStateListener.onScanStateChanged(start);
        }
    }

    public static class ConnectedBluetoothViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        BtDevicesAdapter btDevicesAdapter;
        TextView tvName;
        ImageView ivMusic;
        ImageView ivPhone;

        public ConnectedBluetoothViewHolder(BtDevicesAdapter btDevicesAdapter, @NonNull View itemView) {
            super(itemView);
            this.btDevicesAdapter = btDevicesAdapter;
            tvName = itemView.findViewById(R.id.tv_name);
            ivMusic = itemView.findViewById(R.id.iv_music);
            ivPhone = itemView.findViewById(R.id.iv_phone);
            itemView.setOnClickListener(this);
            ivMusic.setOnClickListener(this);
            ivPhone.setOnClickListener(this);
        }

        private CachedBluetoothDevice getItemDevice() {
            return btDevicesAdapter.mDatas.get(this.getAdapterPosition()).getData();
        }

        public void updateDeviceStatus(Context context){
            CachedBluetoothDevice device = getItemDevice();

            tvName.setText(device.getNameOrAddress());
            ivMusic.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_bt_music, context.getTheme()));
            ivPhone.setImageDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_bt_phone, context.getTheme()));

            boolean isConnectedA2dp = device.getConnectState(BtProfileEnums.A2DP_SINK) == BTConstants.BluetoothAdapter.STATE_CONNECTED;
            boolean isConnectedHfp = device.getConnectState(BtProfileEnums.HFP_CLIENT) == BTConstants.BluetoothAdapter.STATE_CONNECTED;
            boolean isConnectedHid = false; // Game
            boolean isDeviceConnected = isConnectedA2dp || isConnectedHfp || isConnectedHid;
            LogUtils.d(TAG, "updateDeviceStatus: phone=" + isConnectedHfp + " ,music=" + isConnectedA2dp);
            if(isDeviceConnected){
                ivPhone.setSelected(isConnectedHfp);
                ivMusic.setSelected(isConnectedA2dp);
                tvName.setTextColor(context.getColor(R.color.c_7A67FF));
            } else {
                ivPhone.setSelected(false);
                ivMusic.setSelected(false);
                tvName.setTextColor(context.getColor(R.color.white));
            }
            tvName.setTypeface(Typeface.defaultFromStyle(isDeviceConnected ? Typeface.BOLD : Typeface.NORMAL));
        }

        private boolean changIconLoading(ImageView imageView){
            if(imageView.getDrawable() instanceof AnimationDrawable){
                AnimationDrawable loadingDrawable = ((AnimationDrawable)imageView.getDrawable());
                if (loadingDrawable.isRunning()) {
                    LogUtils.d(TAG, "Bt Music Type is changing");
                } else {
                    loadingDrawable.start();
                    return true;
                }
            } else {
                AnimationDrawable loadingDrawable = getLoadingDrawable(imageView.getContext());
                imageView.setImageDrawable(loadingDrawable);
                loadingDrawable.start();
                return true;
            }
            return false;
        }

        @Override
        public void onClick(View v) {
            int id = v.getId();
            if(id == R.id.iv_music){
                if (changIconLoading(ivMusic)) {
                    reverseStateWithConnectedType(getItemDevice(), ConnectProfileOptionEnum.MEDIA);
                }
            } else if(id == R.id.iv_phone){
                if (changIconLoading(ivPhone)) {
                    reverseStateWithConnectedType(getItemDevice(), ConnectProfileOptionEnum.CALL);
                }
            } else {
                changIconLoading(ivMusic);
                changIconLoading(ivPhone);
                BluetoothController.getInstance().reverseBtConnectStatus(getItemDevice());
            }
        }

        private void reverseStateWithConnectedType(CachedBluetoothDevice device, ConnectProfileOptionEnum connectedType){
            BluetoothController bluetoothController = BluetoothController.getInstance();
            if (connectedType == ConnectProfileOptionEnum.CALL) {
                LogUtils.d(TAG, "reverseStateWithConnectedType HFP state is " + device.getConnectState(BtProfileEnums.HFP_CLIENT));
                if (device.getConnectState(BtProfileEnums.HFP_CLIENT) == BTConstants.BluetoothAdapter.STATE_DISCONNECTED) {
                    bluetoothController.disconnectDevice(device, ConnectProfileOptionEnum.CALL);
                    bluetoothController.connectDevice(device, ConnectProfileOptionEnum.CALL);
                } else {
                    bluetoothController.disconnectDevice(device, ConnectProfileOptionEnum.CALL);
                }
            } else if (connectedType == ConnectProfileOptionEnum.MEDIA) {
                LogUtils.d(TAG, "reverseStateWithConnectedType A2DP state is " + device.getConnectState(BtProfileEnums.A2DP_SINK));
                if (device.getConnectState(BtProfileEnums.A2DP_SINK) == BTConstants.BluetoothAdapter.STATE_DISCONNECTED) {
                    bluetoothController.disconnectDevice(device, ConnectProfileOptionEnum.MEDIA);
                    bluetoothController.connectDevice(device, ConnectProfileOptionEnum.MEDIA);
                } else {
                    bluetoothController.disconnectDevice(device, ConnectProfileOptionEnum.MEDIA);
                }
            }
        }
    }

    private static AnimationDrawable getLoadingDrawable(Context context){
        AnimationDrawable animationDrawable = new AnimationDrawable();
        if (context != null) {
            Drawable drawable = ResourcesCompat.getDrawable(context.getResources(), R.drawable.anim_loading_quick, context.getTheme());
            if (drawable != null) {
                animationDrawable.addFrame(drawable, 1000);
            }
        }
        return animationDrawable;
    }

    public static class TextLabelViewHolder extends RecyclerView.ViewHolder {

        private AnimationDrawable animation;
        private TextView tvTitle;
        private ImageView ivLoading;

        public TextLabelViewHolder(@NonNull View itemView) {
            super(itemView);
            tvTitle = itemView.findViewById(R.id.tv_title);
            ivLoading = itemView.findViewById(R.id.iv_loading);
        }

        public void showLoading(boolean show){
            LogUtils.d(TAG, "showLoading: " + show);
            if (animation == null) {
                animation = getLoadingDrawable(itemView.getContext());
                ivLoading.setImageDrawable(animation);
            }
            if (show) {
                animation.start();
                ivLoading.setVisibility(View.VISIBLE);
            } else {
                animation.stop();
                ivLoading.setVisibility(View.GONE);
            }
        }

        public static interface ScanStateListener {
            void onScanStateChanged(boolean start);
        }
    }

    public static class ScanBluetoothViewHolder extends RecyclerView.ViewHolder {

        BtDevicesAdapter btDevicesAdapter;
        TextView tvName;
        public ScanBluetoothViewHolder(BtDevicesAdapter btDevicesAdapter, @NonNull View itemView) {
            super(itemView);

            this.btDevicesAdapter = btDevicesAdapter;
            tvName = itemView.findViewById(R.id.tv_name);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    CachedBluetoothDevice itemDevice = getItemDevice();
                    if(itemDevice != null){
                        if (!itemDevice.isBusy() && itemDevice.startPairing()) {
                            LogUtils.d(TAG, itemDevice.getName() + " pair success!");
                        } else {
                            LogUtils.e(TAG, itemDevice.getName() + " pair failed!");
                        }
                    }
                }
            });
        }

        public void setName(String name){
            tvName.setText(name);
        }

        private CachedBluetoothDevice getItemDevice() {
            return btDevicesAdapter.mDatas.get(this.getAdapterPosition()).getData();
        }
    }
}
